# _*_coding:utf-8_*_
'''
Created on 2013-11-15

@author: jzhai
'''
import numpy
import numpy as np
import scipy
import types


class MyList(list):
    """
    Description:
        This class is used to overload the operators of list.
    Usage:
    """

    def __pos__(self):
        """
        Function:
            overload the "+" unary operator of list
        Parameter:
            None
        Return:
            MyList        Usage:
        """

        temp = filter_str_to_nan(self)
        try:
            temp = scipy.array(temp)
        except:
            temp = scipy.array([])
        return MyList(temp.tolist())

    # end of __pos__

    def __neg__(self):
        """
        Function:
            overload the "-" unary operator of list
        Parameter:
            None
        Return:
           MyList
        Usage:
        """

        temp = filter_str_to_nan(self)
        try:
            temp = scipy.array(temp)
        except:
            temp = scipy.array([])
        temp = -temp
        return MyList(temp.tolist())

    # end of __neg__

    def __add__(self, other):
        """
        Function:
            overload the "+" operator of list
        Parameter:
            other:      other operand
        Return:
            MyList type
        Usage:
        """

        temp = filter_str_to_nan(self)
        try:
            temp = scipy.array(temp)
        except:
            temp = scipy.array([])
        ret_list = []
        if isinstance(other, list) or isinstance(other, tuple):
            other = filter_str_to_nan(other)
            try:
                other = scipy.array(other)
            except:
                other = scipy.array([])
            if temp.shape[0] == 0 or other.shape[0] == 0:
                return MyList([])
            if temp.shape != other.shape:
                # 1-dimensional array
                if len(temp.shape) == 1 and len(other.shape) == 1:
                    min_len = min(temp.shape[0], other.shape[0])
                    result = temp[:min_len] + other[:min_len]
                    return MyList(result.tolist())
                # multi-dimensional array
                else:
                    try:
                        result = temp + other
                        return MyList(result.tolist())
                    except:
                        return MyList([])
            else:
                result = temp + other
                return MyList(result.tolist())
        elif isinstance(other, int) or \
                isinstance(other, float) or \
                isinstance(other, complex):
            result = temp + other
            return MyList(result.tolist())
        else:
            return MyList([])

    # end of __add__

    def __sub__(self, other):
        """
        Function:
            overload the "-" operator of list
        Parameter:
            other:      other operand
        Return:
            MyList type
        Usage:
        """

        temp = filter_str_to_nan(self)
        try:
            temp = scipy.array(temp)
        except:
            temp = scipy.array([])
        ret_list = []
        if isinstance(other, list) or isinstance(other, tuple):
            other = filter_str_to_nan(other)
            try:
                other = scipy.array(other)
            except:
                other = scipy.array([])
            if temp.shape[0] == 0 or other.shape[0] == 0:
                return MyList([])
            if temp.shape != other.shape:
                # 1-dimensional array
                if len(temp.shape) == 1 and len(other.shape) == 1:
                    min_len = min(temp.shape[0], other.shape[0])
                    result = temp[:min_len] - other[:min_len]
                    return MyList(result.tolist())
                # multi-dimensional array
                else:
                    try:
                        result = temp - other
                        return MyList(result.tolist())
                    except:
                        return MyList([])
            else:
                result = temp - other
                return MyList(result.tolist())
        elif isinstance(other, int) or \
                isinstance(other, float) or \
                isinstance(other, complex):
            result = temp - other
            return MyList(result.tolist())
        else:
            return MyList([])

    # end of __sub__

    def __mul__(self, other):
        """
        Function:
            overload the "*" operator of list
        Parameter:
            other:      other operand
        Return:
            MyList type
        Usage:
        """

        temp = filter_str_to_nan(self)
        try:
            temp = numpy.array(temp)
            # temp = scipy.array(temp)
        except:
            temp = numpy.array([])
            # temp = scipy.array([])
        ret_list = []
        if isinstance(other, list) or isinstance(other, tuple):
            other = filter_str_to_nan(other)
            try:
                other = numpy.array(other)
                # other = scipy.array(other)
            except:
                other = numpy.array([])
                # other = scipy.array([])
            if temp.shape[0] == 0 or other.shape[0] == 0:
                return MyList([])
            if temp.shape != other.shape:
                # 1-dimensional array
                if len(temp.shape) == 1 and len(other.shape) == 1:
                    min_len = min(temp.shape[0], other.shape[0])
                    result = temp[:min_len] * other[:min_len]
                    return MyList(result.tolist())
                # multi-dimensional array
                else:
                    try:
                        result = temp * other
                        return MyList(result.tolist())
                    except:
                        return MyList([])
            else:
                result = temp * other
                return MyList(result.tolist())
        elif isinstance(other, int) or \
                isinstance(other, float) or \
                isinstance(other, complex):
            result = temp * other
            return MyList(result.tolist())
        else:
            return MyList([])

    # end of __mul__

    def __div__(self, other):
        """
        Function:
            overload the "/" operator of list
        Parameter:
            other:      other operand
        Return:
            MyList type
        Usage:
        """

        temp = filter_str_to_nan(self)
        try:
            temp = scipy.array(temp)
        except:
            temp = scipy.array([])
        ret_list = []
        if isinstance(other, list) or isinstance(other, tuple):
            other = filter_str_to_nan(other)
            try:
                other = scipy.array(other)
            except:
                other = scipy.array([])
            if temp.shape[0] == 0 or other.shape[0] == 0:
                return MyList([])
            if temp.shape != other.shape:
                # 1-dimensional array
                if len(temp.shape) == 1 and len(other.shape) == 1:
                    min_len = min(temp.shape[0], other.shape[0])
                    result = temp[:min_len] / other[:min_len]
                    return MyList(result.tolist())
                # multi-dimensional array
                else:
                    try:
                        result = temp / other
                        return MyList(result.tolist())
                    except:
                        return MyList([])
            else:
                result = temp / other
                return MyList(result.tolist())
        elif isinstance(other, int) or \
                isinstance(other, float) or \
                isinstance(other, complex):
            result = temp / other
            return MyList(result.tolist())
        else:
            return MyList([])

    # end of __div__

    def __mod__(self, other):
        """
        Function:
            overload the "%" operator of list
        Parameter:
            other:      other operand
        Return:
            MyList type
        Usage:
        """

        temp = filter_str_to_nan(self)
        try:
            temp = scipy.array(temp)
        except:
            temp = scipy.array([])
        ret_list = []
        if isinstance(other, list) or isinstance(other, tuple):
            other = filter_str_to_nan(other)
            try:
                other = scipy.array(other)
            except:
                other = scipy.array([])
            if temp.shape[0] == 0 or other.shape[0] == 0:
                return MyList([])
            if temp.shape != other.shape:
                # 1-dimensional array
                if len(temp.shape) == 1 and len(other.shape) == 1:
                    min_len = min(temp.shape[0], other.shape[0])
                    result = temp[:min_len] % other[:min_len]
                    return MyList(result.tolist())
                # multi-dimensional array
                else:
                    try:
                        result = temp % other
                        return MyList(result.tolist())
                    except:
                        return MyList([])
            else:
                result = temp % other
                return MyList(result.tolist())
        elif isinstance(other, int) or \
                isinstance(other, float) or \
                isinstance(other, complex):
            result = temp % other
            return MyList(result.tolist())
        else:
            return MyList([])

    # end of __mod__

    def tolist(self):
        """
        Function:
            convert MyList to 1-dimensional array (list)
        Parameter:
            None
        Return:
            list
        Usage:
        """

        temp = scipy.ravel(self)
        # return map(lambda x: (scipy.isnan(x) or scipy.isinf(x)) and "#REF" or x, temp)
        return map(lambda x: (x == '#REF') and "#REF" or x, temp)
    # end of tolist


class MyStr(str):
    """
    Description:
        This class is used to overload the operators of string.
    Usage:
    """

    def __pos__(self):
        """
        Function:
            overload the "+" unary operator of string
        Parameter:
            None
        Return:
            MyStr
        Usage:
        """

        return MyStr("#REF")

    # end of __pos__

    def __neg__(self):
        """
        Function:
            overload the "-" unary operator of string
        Parameter:
            None
        Return:
            MyStr
        Usage:
        """

        return MyStr("#REF")

    # end of __pos__

    def __add__(self, other):
        """
        Function:
            overload the "+" operator of string
        Parameter:
            other:      other operand
        Return:
            MyStr or MyList
        Usage:
        """

        if isinstance(other, list):
            return MyList(other) + self
        else:
            return MyStr("#REF")

    # end of __add__

    def __sub__(self, other):
        """
        Function:
            overload the "-" operator of string
        Parameter:
            other:      other operand
        Return:
            MyStr
        Usage:
        """

        if isinstance(other, list):
            return MyList(other) * (-1) + self
        else:
            return MyStr("#REF")

    # end of __sub__

    def __mul__(self, other):
        """
        Function:
            overload the "*" operator of string
        Parameter:
            other:      other operand
        Return:
            MyStr
        Usage:
        """

        if isinstance(other, list):
            return MyList(other) * self
        else:
            return MyStr("#REF")

    # end of __mul__

    def __div__(self, other):
        """
        Function:
            overload the "/" operator of string
        Parameter:
            other:      other operand
        Return:
            MyStr
        Usage:
        """

        if isinstance(other, list):
            temp_list = [self for i in range(len(other))]
            return MyList(temp_list) / MyList(other)
        else:
            return MyStr("#REF")

    # end of __sub__

    def __mod__(self, other):
        """
        Function:
            overload the "%" operator of string
        Parameter:
            other:      other operand
        Return:
            MyStr
        Usage:
        """

        if isinstance(other, list):
            temp_list = [self for i in range(len(other))]
            return MyList(temp_list) % MyList(other)
        else:
            return MyStr("#REF")
    # end of __sub__


# end of class MyStr

class MyFloat(float):
    """
    Description:
        This class is used to overload the operators of float.
    Usage:
    """

    def __pos__(self):
        """
        Function:
            overload the "+" unary operator of float
        Parameter:
            None
        Return:
            MyFloat
        Usage:
        """

        return MyFloat(self)

    # end of __pos__

    def __neg__(self):
        """
        Function:
            overload the "-" unary operator of float
        Parameter:
            None
        Return:
           MyFloat
        Usage:
        """

        # return MyFloat(scipy.negative(self))
        return MyFloat(numpy.negative(self))

    # end of __neg__

    def __add__(self, other):
        """
        Function:
            overload the "+" operator of float
        Parameter:
            other:      other operand
        Return:
            MyFloat, MyComplex, or MyList type
        Usage:
        """

        if isinstance(other, list) or \
                isinstance(other, tuple):
            return MyList(other) + self
        elif isinstance(other, float) or \
                isinstance(other, int):
            return MyFloat(scipy.add(self, other))
        elif isinstance(other, complex):
            return MyComplex(self) + other
        else:
            return MyStr("#REF")

    # end of __add__

    def __sub__(self, other):
        """
        Function:
            overload the "-" operator of float
        Parameter:
            other:      other operand
        Return:
            MyFloat, MyComplex, or MyList type
        Usage:
        """

        if isinstance(other, list) or \
                isinstance(other, tuple):
            return MyList(other) * (-1) + self
        elif isinstance(other, float) or \
                isinstance(other, int):
            return MyFloat(scipy.subtract(self, other))
        elif isinstance(other, complex):
            return MyComplex(self) - other
        else:
            return MyStr("#REF")

    # end of __sub__

    def __mul__(self, other):
        """
        Function:
            overload the "*" operator of float
        Parameter:
            other:      other operand
        Return:
            MyFloat, MyComplex, or MyList type
        Usage:
        """

        if isinstance(other, list) or \
                isinstance(other, tuple):
            return MyList(other) * self
        elif isinstance(other, float) or \
                isinstance(other, int):
            return MyFloat(scipy.multiply(self, other))
        elif isinstance(other, complex):
            return MyComplex(self) * other
        else:
            return MyStr("#REF")

    # end of __mul__

    def __div__(self, other):
        """
        Function:
            overload the "/" operator of float
        Parameter:
            other:      other operand
        Return:
            MyFloat, MyComplex, or MyList type
        Usage:
        """

        if isinstance(other, list) or \
                isinstance(other, tuple):
            temp_list = [self for i in range(len(other))]
            return MyList(temp_list) / MyList(other)
        elif isinstance(other, float) or \
                isinstance(other, int):
            return MyFloat(np.divide(self, other))
        elif isinstance(other, complex):
            return MyComplex(self) / other
        else:
            return MyStr("#REF")

    # end of __div__

    def __mod__(self, other):
        """
        Function:
            overload the "%" operator of float
        Parameter:
            other:      other operand
        Return:
            MyFloat, MyComplex, or MyList type
        Usage:
        """

        if isinstance(other, list) or \
                isinstance(other, tuple):
            temp_list = [self for i in range(len(other))]
            return MyList(temp_list) % MyList(other)
        elif isinstance(other, float) or \
                isinstance(other, int):
            return MyFloat(scipy.mod(self, other))
        elif isinstance(other, complex):
            return MyComplex(self) % other
        else:
            return MyStr("#REF")
    # end of __mod__


# end of class MyFloat


class MyInt(int):
    """
    Description:
        This class is used to overload the operators of int.
    Usage:
    """

    def __pos__(self):
        """
        Function:
            overload the "+" unary operator of int
        Parameter:
            None
        Return:
            MyInt
        Usage:
        """
        return MyInt(self)

    def __neg__(self):
        """
        Function:
            overload the "-" unary operator of int
        Parameter:
            None
        Return:
           MyInt
        Usage:
        """
        return MyInt(scipy.negative(self))

    def __add__(self, other):
        """
        Function:
            overload the "+" operator of int
        Parameter:
            other:      other operand
        Return:
            MyFloat, MyInt, MyComplex or MyList type
        Usage:
        """

        if isinstance(other, list) or \
                isinstance(other, tuple):
            return MyList(other) + self
        elif isinstance(other, float):
            return MyFloat(other) + self
        elif isinstance(other, int):
            return MyInt(scipy.add(self, other))
        elif isinstance(other, complex):
            return MyComplex(self) + other
        else:
            return MyStr("#REF")

    # end of __add__

    def __sub__(self, other):
        """
        Function:
            overload the "-" operator of int
        Parameter:
            other:      other operand
        Return:
            MyFloat, MyInt, MyComplex or MyList type
        Usage:
        """

        if isinstance(other, list) or \
                isinstance(other, tuple):
            return MyList(other) * (-1) + self
        elif isinstance(other, float):
            return MyFloat(other) * (-1) + self
        elif isinstance(other, int):
            return MyInt(scipy.subtract(self, other))
        elif isinstance(other, complex):
            return MyComplex(other) * (-1) + self
        else:
            return MyStr("#REF")

    # end of __sub__

    def __mul__(self, other):
        """
        Function:
            overload the "*" operator of int
        Parameter:
            other:      other operand
        Return:
            MyFloat, MyInt, MyComplex or MyList type
        Usage:
        """

        if isinstance(other, list) or \
                isinstance(other, tuple):
            return MyList(other) * self
        elif isinstance(other, float):
            return MyFloat(other) * self
        elif isinstance(other, int):
            return MyInt(scipy.multiply(self, other))
        elif isinstance(other, complex):
            return MyComplex(self) * other
        else:
            return MyStr("#REF")

    # end of __mul__

    def __div__(self, other):
        """
        Function:
            overload the "/" operator of int
        Parameter:
            other:      other operand
        Return:
            MyFloat, MyInt, MyComplex or MyList type
        Usage:
        """

        if isinstance(other, list) or \
                isinstance(other, tuple):
            temp_list = [self for i in range(len(other))]
            return MyList(temp_list) / MyList(other)
        elif isinstance(other, float):
            return MyFloat(self) / other
        elif isinstance(other, int):
            return MyInt(scipy.divide(self, other))
        elif isinstance(other, complex):
            return MyComplex(self) / other
        else:
            return MyStr("#REF")

    # end of __div__

    def __mod__(self, other):
        """
        Function:
            overload the "/" operator of int
        Parameter:
            other:      other operand
        Return:
            MyInt or MyList type
        Usage:
        """

        if isinstance(other, list) or \
                isinstance(other, tuple):
            temp_list = [self for i in range(len(other))]
            return MyList(temp_list) % MyList(other)
        elif isinstance(other, float):
            return MyFloat(self) % other
        elif isinstance(other, int):
            return MyInt(scipy.mod(self, other))
        elif isinstance(other, complex):
            return MyComplex(self) % other
        else:
            return MyStr("#REF")
    # end of __mod__


# end of class MyInt
def filter_str_to_nan(input_list, replace="nan", b_remove=False):
    """
    Function:
        filter string items inside an input list to scipy.NAN
    Parameter:
        input_list:             the input list
    Return:
        list:                   filtered list
    Usage:
    """

    if isinstance(input_list, scipy.ndarray) or \
            isinstance(input_list, scipy.matrix):
        return input_list
    if not isinstance(input_list, list) and \
            not isinstance(input_list, tuple):
        return []
    replace = replace.lower()
    if replace == "nan":
        replace = scipy.NAN
    elif replace == "-inf":
        replace = -scipy.inf
    elif replace in ("inf", "+inf"):
        replace = scipy.inf
    else:
        replace = scipy.NAN
    ret = []
    for item in input_list:
        if isinstance(item, str):
            ret.append(replace)
            continue
        if b_remove and (scipy.isinf(item) or scipy.isnan(item)):
            # ret.append(scipy.NAN)
            continue
        if isinstance(item, int) \
                or isinstance(item, float) \
                or isinstance(item, complex):
            ret.append(item)
            continue

        ret.append(filter_str_to_nan(item))
    return ret


def DELTA(x):
    """
    Function:
        return the delta value of input argument
    Parameter:
        x:      input argument
    Return:
        delta value
    Usage:
    """

    if isinstance(x, list) or \
            isinstance(x, tuple):
        temp = filter_str_to_nan(x)
        try:
            temp = scipy.array(temp)
        except:
            temp = scipy.array([])
        if temp.shape[0] == 0:
            return MyList([])
        diff_val = scipy.diff(temp, axis=-1)
        if diff_val.dtype == scipy.int_:
            diff_val = diff_val.astype(scipy.float_)
        result = scipy.insert(diff_val, 0, scipy.NAN, axis=-1)
        result = MyList(result.tolist())
        if len(result) > 0:
            if isinstance(result[0], list):
                for item in result:
                    item[0] = MyStr("#REF")
            else:
                result[0] = MyStr("#REF")
        return result
    else:
        return MyList([])


def DIFF(x, y):
    """
    Function:
        return the delta difference value of x, y
    Parameter:
        x:      input argument
        y:
    Return:
        dy/dx
    Usage:
    """
    result = DELTA(y) / DELTA(x)
    if len(result) > 0:
        if isinstance(result[0], list):
            pass
            for item in result:
                item[0] = MyStr("#REF")
        else:
            result[0] = MyStr("#REF")
    return result


def ABS(x):
    """
    Function:
        return absolute value of input argument
    Parameter:
        x:      input argument
    Return:
        absolute value
    Usage:
    """

    if isinstance(x, float):
        return MyFloat(scipy.absolute(x))
    elif isinstance(x, int):
        return MyInt(scipy.absolute(x))
    elif isinstance(x, complex):
        return MyFloat(scipy.absolute(x))
    elif isinstance(x, list) or \
            isinstance(x, tuple):
        temp = filter_str_to_nan(x)
        try:
            temp = scipy.array(temp)
        except:
            temp = scipy.array([])
        if temp.shape[0] == 0:
            return MyList([])
        result = scipy.absolute(temp)
        return MyList(result.tolist())
    else:
        return MyList([])


def MIN(x):
    """
    Function:
        return the maximum value of input argument
    Parameter:
        x:      input argument
    Return:
        average value
    Usage:
    """

    if isinstance(x, float) or \
            isinstance(x, int):
        return MyFloat(x)
    elif isinstance(x, complex):
        return MyComplex(x)
    elif isinstance(x, list) or \
            isinstance(x, tuple):
        temp = filter_str_to_nan(x, b_remove=True)
        try:
            temp = scipy.array(temp)
        except:
            temp = scipy.array([])
        if temp.shape[0] == 0:
            return MyList([])
        result = temp.min(axis=-1)
        if isinstance(result, int):
            return MyInt(result)
        elif isinstance(result, float):
            return MyFloat(result)
        elif isinstance(result, complex):
            return MyComplex(result)
        else:
            return MyList(result.tolist())
    else:
        return MyList([])


def MINPOS(x):
    """
    Function:
        return the position of the minimum value
    Parameter:
        x:      input argument
    Return:
        position of the minimum value
    Usage:
    """

    if isinstance(x, float):
        return MyInt(0)
    elif isinstance(x, int):
        return MyInt(0)
    elif isinstance(x, list):
        min_val = MIN(x)
        if isinstance(min_val, float) or \
                isinstance(min_val, int):
            return MyInt(x.index(min_val))
        else:
            MyList([])
    else:
        return MyList([])


def MAX(x):
    """
    Function:
        return the maximum value of input argument
    Parameter:
        x:      input argument
    Return:
        average value
    Usage:
    """

    if isinstance(x, float) or \
            isinstance(x, int):
        return MyFloat(x)
    elif isinstance(x, complex):
        return MyComplex(x)
    elif isinstance(x, list) or \
            isinstance(x, tuple):
        temp = filter_str_to_nan(x, "-inf", b_remove=True)
        try:
            temp = scipy.array(temp)
        except:
            temp = scipy.array([])
        if temp.shape[0] == 0:
            return MyList([])
        result = temp.max(axis=-1)
        if isinstance(result, int):
            return MyInt(result)
        elif isinstance(result, float):
            return MyFloat(result)
        elif isinstance(result, complex):
            return MyComplex(result)
        else:
            return MyList(result.tolist())
    else:
        return MyList([])


# end of MAX


def MAXPOS(x):
    """
    Function:
        return the position of the maximum value
    Parameter:
        x:      input argument
    Return:
        position of the maximum value
    Usage:
    """

    if isinstance(x, float):
        return MyInt(0)
    elif isinstance(x, int):
        return MyInt(0)
    elif isinstance(x, list):
        if len(x) == 0:
            return MyList([])
        max_val = MAX(x)
        if isinstance(max_val, float):
            return MyInt(x.index(max_val))
        else:
            return MyList([])
    else:
        return MyList([])


def FINDD(v, x, start_pos):
    """
    Function:
        find down
    Parameter:
        v:          array to be searched
        x:          the value to be targeted
        start_pos:  position from which searching begins
    Return:
        index of the value
    Usage:
    """

    if not isinstance(v, list):
        return MyList([])
    if not isinstance(start_pos, int) \
            and not isinstance(start_pos, float):
        return MyList([])
    if isinstance(x, list) and len(x) == 1:
        x = x[0]
    if start_pos < 0:
        return MyList([])
    temp_v = v[start_pos:]
    if not temp_v:
        return MyList([])
    temp_v = MyList(temp_v) - x
    temp_v = ABS(temp_v)
    min_pos = MINPOS(temp_v)
    return MyInt(min_pos + start_pos)


def FINDLIN(v, x, start_pos):
    """
    Function:
        find using linear interpolation from up to down
    Parameter:
        v:          array to be searched
        x:          the value to be targeted
        start_pos:  position from which searching begins
    Return:
        index of the value
    Usage:
    """

    pos = FINDD(v, x, start_pos)
    # print "****pos=",pos
    if not isinstance(pos, int):
        return MyList([])

    # if (pos - start_pos) == (len(v) - 1):
    #    LogManager.logWarning('Function "FINDLIN" has used the end point for interpolation')
    # elif (pos == start_pos):
    #    LogManager.logWarning('Function "FINDLIN" has used the start point for interpolation')
    val = AT(v, pos)
    prev_val = AT(v, pos - 1)
    next_val = AT(v, pos + 1)
    # print "val=",val
    # print "prev_val=",prev_val
    # print "next_val=",next_val
    if val == x or isinstance(val, str):
        return MyFloat(pos)
    pos = MyFloat(pos)
    if val:
        if prev_val:
            if (prev_val <= x < val) or (prev_val >= x > val):
                pos = pos - 1 + (x - prev_val) / (val - prev_val)
                return pos
        if next_val:
            if (val < x <= next_val) or (val > x >= next_val):
                pos = pos + (x - val) / (next_val - val)
                return pos
    return pos


def AT(x, pos):
    """
    Function:
        extract and return a single value from the input argument
    Parameter:
        x:      input argument
        pos:    the position of a single value
    Return:
        a single value
    Usage:
    """

    if not isinstance(pos, int) and \
            not isinstance(pos, float):
        return MyList([])
    if isinstance(x, float):
        if pos == 0:
            return MyFloat(x)
        else:
            return MyList([])
    elif isinstance(x, int):
        if pos == 0:
            return MyFloat(x)
        else:
            return MyList([])
    elif isinstance(x, list):
        len_x = len(x)
        if len_x == 0:
            return MyList([])
        if pos < 0 or pos > (len_x - 1):
            return MyList([])
        else:
            low_pos = int(pos)
            res_pos = pos - low_pos
            if res_pos == 0:
                if isinstance(x[low_pos], str):
                    return MyList([])
                else:
                    return MyFloat(x[low_pos])
            else:
                high_pos = low_pos + 1
                if isinstance(x[low_pos], str):
                    if isinstance(x[high_pos], str):
                        return MyList([])
                    else:
                        return MyFloat(x[high_pos])
                elif isinstance(x[high_pos], str):
                    if isinstance(x[low_pos], str):
                        return MyList([])
                    else:
                        return MyFloat(x[low_pos])
                else:
                    x[low_pos] = MyFloat(x[low_pos])
                    x[high_pos] = MyFloat(x[high_pos])
                    val = x[low_pos] + (x[high_pos] - x[low_pos]) * res_pos
                    return val
    else:
        return MyList([])


def DELTA_2(x):
    """
    Function:
        Return Xn+1/Xn
    """
    x_n2 = MyList(x[1:])
    x_n1 = MyList(x[:-1])
    val = x_n2 // x_n1
    val.insert(0, MyStr("#REF"))
    return val


"""
aa=[-1,-2,3,-4.0]
aa1=aa[:-1]
bb=aa[1:]

aa_list = MyList(aa1)
bb_list=MyList(bb)
print type(aa_list)
cc=bb_list/aa_list
print aa_list,bb_list

#print max(bb)
print cc
cc.append(5)
print cc
"""
